const commondUtil = require('./commondUtils.js');
const StorageUtils = {};

// 应用名称
const APP_NAME = 'm3-clock';
// 应用名称-简称
const APP_NAME_ABBREVIATION = 'clock';

// 根目录
StorageUtils.ROOT_DIR_NAME = files.join(files.getSdcardPath(), APP_NAME);

// 日志存储文件名称
StorageUtils.LOG_FILENAME = 'log.txt';
// 配置存储文件名称
StorageUtils.SETTING_FILENAME = 'setting.txt';

// 配置存储空间名称
StorageUtils.SETTING_STORAGE_NAME = APP_NAME_ABBREVIATION + '-setting-storage';
// 配置存储文件名称
StorageUtils.SETTING_STORAGE_KEY = 'settingObj';
// 公共存储空间名称
StorageUtils.PUCLIC_STORAGE_NAME = APP_NAME_ABBREVIATION + '-public-storage';
// 应用首次启用时间
StorageUtils.APP_INIT_TIME = APP_NAME_ABBREVIATION + '-init-time';


/**
 * 覆盖保存应用数据
 * @param name
 * @param key
 * @param value
 * @returns {boolean}
 */
StorageUtils.saveLocalData = (name, key, value) => {
    try {
        storages.create(name).put(key, value);
    } catch (e) {
        console.error("覆盖保存数据至本地异常", name, key, value, e);
        return false;
    }
    return true;
}
/**
 * 增量保存应用数据
 * @param name
 * @param key
 * @param value
 * @param delimiter
 * @returns {boolean}
 */
StorageUtils.mergeLocalData = (name, key, value, delimiter) => {
    try {
        const valueType = typeof value;
        const storageObj = storages.create(name);
        let allLocalData = storageObj.get(key, valueType == 'object' ? [] : '');
        switch (valueType) {
            case "object":
                if (Array.isArray(value)) {
                    value.forEach(item => {
                        allLocalData.push(item);
                    })
                } else {
                    allLocalData.push(item);
                }
                break;
            case "string":
                if (!delimiter) {
                    delimiter = '@@@';
                }
                allLocalData += delimiter + value;
                break;
            default:
                return false;
        }
        storageObj.put(key, allLocalData);
    } catch (e) {
        console.error("增量保存数据至本地异常", name, key, value, e);
        return false;
    }
    return true;
}
/**
 * 获取应用数据
 * @param name
 * @param key
 * @param defaultValue
 * @returns {object|null}
 */
StorageUtils.getLocalData = (name, key, defaultValue) => {
    try {
        return storages.create(name).get(key, defaultValue);
    } catch (e) {
        console.error("读取本地数据异常", name, key, defaultValue, e);
        return defaultValue;
    }
}
/**
 * 删除应用数据
 * @param name
 * @param key
 * @returns {boolean}
 */
StorageUtils.deleteLocalData = (name, key) => {
    try {
        const storage = storages.create(name);
        if (storage.contains(key)) {
            storage.remove(key);
        }
    } catch (e) {
        console.error("删除本地数据异常", e)
        return false;
    }
    return true;
}


/**
 * 校验文件路径是否存在，不存在则新增
 * @param filename
 * @returns {boolean}
 */
StorageUtils.validFilepath = (filename) => {
    if (commondUtil.isEmpty(filename)) {
        return false;
    }
    const filepath = files.join(StorageUtils.ROOT_DIR_NAME, filename);
    let flag = true;
    try {
        // 确保路径所在的文件夹存在，不存在则创建
        files.ensureDir(filepath);
        if (!files.exists(filepath)) {
            flag = files.create(filepath);
            if (!flag) {
                console.error("创建文件异常.filepath:{%s}", filepath);
            }
        }
    } catch (e) {
        console.error("创建文件或文件夹异常.filepath:{%s}", filepath, e);
        flag = false;
    }
    return flag;
}

/**
 * 获取文件数据
 * @param filename
 * @returns {object|null}
 */
StorageUtils.getFileData = (filename) => {
    if (commondUtil.isEmpty(filename)) {
        return null;
    }
    let data = null;
    const filepath = files.join(StorageUtils.ROOT_DIR_NAME, filename);
    try {
        if (!files.exists(filepath)) {
            // console.info("读取的文件不存在", filepath);
            return null;
        }
        data = files.read(filepath);
        if (commondUtil.isNotEmpty(data)) {
            data = JSON.parse(data);
        }
    } catch (e) {
        console.error("读取文件数据异常.filepath:{%s}", filepath, e);
    }
    return data;
}


/**
 * 保存文件数据（追加）
 * @param {string} filename
 * @param {object} data
 * @returns {boolean}
 */
StorageUtils.saveToFile = (filename, data) => {
    if (commondUtil.isEmpty(data)) {
        return false;
    }
    const filepath = files.join(StorageUtils.ROOT_DIR_NAME, filename);
    try {
        if (!StorageUtils.validFilepath(filename)) {
            return false;
        }
        let allData = files.read(filepath);
        if (commondUtil.isNotEmpty(allData)) {
            allData = JSON.parse(allData);
        } else {
            allData = [];
        }
        allData.push(data);
        files.write(filepath, JSON.stringify(allData));
    } catch (e) {
        console.error("保存(追加)数据到文件异常.filepath: %s", filepath, data, e);
        return false;
    }
    return true;
}

/**
 * 保存文件数据（覆盖）
 * @param filename
 * @param data
 * @returns {boolean}
 */
StorageUtils.saveToFileCover = (filename, data) => {
    if (commondUtil.isEmpty(data)) {
        return false;
    }
    const filepath = files.join(StorageUtils.ROOT_DIR_NAME, filename);
    try {
        if (!StorageUtils.validFilepath(filename)) {
            return false;
        }
        files.write(filepath, JSON.stringify(data));
    } catch (e) {
        console.error("保存(覆盖)数据到文件异常.filepath:{%s}", filepath, data, e);
        return false;
    }
    return true;
}


/**
 * 根据日期范围获取文件数据
 * @param filename
 * @param startDate
 * @param endDate
 * @returns {Array|null}
 */
StorageUtils.geFileDataByDateRange = (filename, startDate, endDate) => {
    if (commondUtil.isEmpty(filename)) {
        return null;
    }
    // 为空则取应用最初时间
    if (commondUtil.isEmpty(startDate)) {
        startDate = StorageUtils.getLocalData(StorageUtils.PUCLIC_STORAGE_NAME, StorageUtils.APP_INIT_TIME, new Date().getTime());
    }
    const dateStrList = commondUtil.getDateRange(startDate, endDate || new Date(), false);
    if (commondUtil.isEmpty(dateStrList)) {
        return [];
    }
    const allData = [];
    dateStrList.forEach(dateStr => {
        let data = StorageUtils.getFileData(files.join(dateStr, filename));
        if (commondUtil.isNotEmpty(data)) {
            if (Array.isArray(data)) {
                data.forEach(item => allData.push(item));
            } else {
                allData.push(data)
            }
        }
    });
    return allData;
}


/**
 * 根据日期范围获取应用内存数据
 * @param storageName
 * @param startDate
 * @param endDate
 * @returns {Array|null}
 */
StorageUtils.getLocalDataByDateRange = (storageName, startDate, endDate) => {
    if (commondUtil.isEmpty(storageName)) {
        return null;
    }
    if (commondUtil.isEmpty(startDate)) {
        startDate = StorageUtils.getLocalData(StorageUtils.PUCLIC_STORAGE_NAME, StorageUtils.APP_INIT_TIME, new Date().getTime());
    }
    const dateStrList = commondUtil.getDateRange(startDate, endDate || new Date(), true);
    if (commondUtil.isEmpty(dateStrList)) {
        return [];
    }
    const allData = [];
    const storageObj = storages.create(storageName);
    dateStrList.forEach(dateStr => {
        storageObj.get(dateStr, []).forEach(item => {
            allData.push(item);
        });
    });
    return allData;
}

/**
 * 持久化数据（内存+文件）
 * @param {object} data
 * @param {string} storageName
 * @param {string} filename
 * @returns {boolean}
 */
StorageUtils.persistenceData = (data, storageName, filename) => {
    if (commondUtil.isEmpty(data)) {
        return false;
    }
    // storageKey: yyyyMMdd
    let flag = StorageUtils.mergeLocalData(storageName, commondUtil.formatDate(new Date(), false, true), data);
    if (flag) {
        // yyyy-MM-dd/filename
        flag = StorageUtils.saveToFile(files.join(commondUtil.getCurrentDateStr(), filename), data);
    }
    return flag;
}


/**
 * 导出内存数据至文件
 * @param {String}  storageName   存储空间名称
 * @param {Date}    startDate     起始时间（年月日）
 * @param {Date}    endDate       结束时间（年月日）
 * @returns {boolean}
 */
StorageUtils.exportLocalDataToFile = (storageName, startDate, endDate) => {
    // storageName-yyyyMMddHHmmss(startDate-endDate)
    const exportFilename = storageName + commondUtil.formatDate(startDate, true, true)
        + '(' + commondUtil.formatDate(startDate, false, true) + commondUtil.formatDate(endDate, false, true) + ')';
    return StorageUtils.saveToFile(exportFilename, StorageUtils.getLocalDataByDateRange(storageName, startDate, endDate));
}


/**
 * 设置日志文件存储目录，每天更新
 * @param {boolean} dailyFlag 是否分天存储
 */
StorageUtils.setLogDir = (dailyFlag) => {
    // 设置日志存储路径
    let logFilepath = StorageUtils.ROOT_DIR_NAME;
    if (dailyFlag) {
        // 分天存储 yyyy-MM-dd
        logFilepath = files.join(logFilepath, commondUtil.getCurrentDateStr());
    }
    logFilepath = files.join(logFilepath, StorageUtils.LOG_FILENAME);
    console.setGlobalLogConfig({"file": logFilepath});
    console.info("设置日志文件路径：", logFilepath);

    if (!dailyFlag) {
        return;
    }

    const setLogDirTimestamp = new Date().getTime();
    const date = new Date();
    date.setHours(0, 0, 0, 0);
    date.setDate(date.getDate() + 1);
    const updateLogDirTimestamp = date.getTime() - setLogDirTimestamp;
    setTimeout(() => {
        StorageUtils.setLogDir(dailyFlag);
    }, updateLogDirTimestamp)
}

/**
 * 加载配置文件
 * @param {object} defaultSettingData
 * @returns {object}
 */
StorageUtils.loadSettingData = (defaultSettingData) => {
    if (commondUtil.isEmpty(defaultSettingData)) {
        console.error("默认配置为空!", defaultSettingData);
        return;
    }
    let data = StorageUtils.getFileData(StorageUtils.SETTING_FILENAME);
    if (commondUtil.isEmpty(data)) {
        console.info("配置文件为空，取默认配置");
        data = defaultSettingData;
    } else {
        if (typeof data === 'string') {
            data = JSON.parse(data);
        }
        // 校验配置文件数据，不存在的配置属性，取默认配置中的
        for (let key in defaultSettingData) {
            if (data[key] == null) {
                data[key] = defaultSettingData[key];
            }
        }
    }
    // 存到内存
    // StorageUtils.saveLocalData(StorageUtils.SETTING_STORAGE_NAME, StorageUtils.SETTING_STORAGE_KEY, data);
    return data;
}

module.exports = StorageUtils;